package com.wlz.files;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.internal.FileHelper;

import java.io.*;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * zip压缩 工具类
 * </p>
 *
 * @author liqi
 * @since 2019-11-25
 */
@Slf4j
public class ZipCompressUtil {

    private static final int BUFFER_SIZE = 2 * 1024;

    /**
     * 初始化
     */
    private ZipCompressUtil() {
    }

    /**
     * 按文件压缩
     *
     * @param sourcePathList 源文件列表
     * @param zipPath        压缩文件保存路径
     * @return
     */
    public static Boolean toZip(List<String> sourcePathList, String zipPath) {
        try {
            FileOutputStream fos = new FileOutputStream(new File(zipPath));
            ZipOutputStream zos = new ZipOutputStream(fos);
            for (String sourcePath : sourcePathList) {
                File sourceFile = new File(sourcePath);
                String fileName = sourceFile.getName();
                FileInputStream fis = new FileInputStream(sourceFile);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int len = -1;
                byte[] buf = new byte[BUFFER_SIZE];
                while ((len = fis.read(buf)) != -1) {
                    baos.write(buf, 0, len);
                }
                baos.close();
                fis.close();
                byte[] fileContent = baos.toByteArray();
                ZipEntry zipEntry = new ZipEntry(fileName);
                zos.putNextEntry(zipEntry);
                zos.write(fileContent);
                zos.closeEntry();
            }
            zos.close();
            fos.close();
            return true;
        } catch (Exception ex) {
            log.error("压缩文件异常", ex);
            return false;
        }
    }



    /**
     * 按文件夹压缩
     *
     * @param sourcePath 源文件夹路径
     * @param zipPath    压缩文件保存路径
     * @return
     */
    public static Boolean toZip(String sourcePath, String zipPath) {
        try {
            ZipOutputStream zos = null;
            FileOutputStream out = new FileOutputStream(new File(zipPath));
            try {
                zos = new ZipOutputStream(out);
                File sourceFile = new File(sourcePath);
                compress(sourceFile, zos, sourceFile.getName(), true);
            } catch (Exception e) {
                throw new RuntimeException("zip error from ZipCompressUtil", e);
            } finally {
                if (zos != null) {
                    try {
                        zos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return true;
        } catch (Exception e) {
            log.error("压缩文件异常", e);
            return false;
        }
    }

    /**
     * 递归压缩
     *
     * @param sourceFile       源文件
     * @param zos              zip输出流
     * @param name             压缩后的名称
     * @param KeepDirStructure 是否保留原来的目录结构(true:保留 false:不保留)
     * @throws Exception
     */
    private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure) throws Exception {
        byte[] buf = new byte[BUFFER_SIZE];
        if (sourceFile.isFile()) {
            zos.putNextEntry(new ZipEntry(name));
            int len;
            FileInputStream in = new FileInputStream(sourceFile);
            while ((len = in.read(buf)) != -1) {
                zos.write(buf, 0, len);
            }
            zos.closeEntry();
            in.close();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                if (KeepDirStructure) {
                    zos.putNextEntry(new ZipEntry(name + "/"));
                    zos.closeEntry();
                }
            } else {
                for (File file : listFiles) {
                    if (KeepDirStructure) {
                        compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
                    } else {
                        compress(file, zos, file.getName(), KeepDirStructure);
                    }
                }
            }
        }
    }

    /**
     * 解压文件
     */
    public static Boolean unZip(String zipFile, String path) {
        try {
            File pathfile = new File(path);
            if (!pathfile.exists()) {
                pathfile.mkdirs();
            }
            FileInputStream fis = new FileInputStream(new File(zipFile));
            ZipInputStream zis = new ZipInputStream(fis, Charset.forName("GBK"));
            ZipEntry zipEntry = null;
            while ((zipEntry = zis.getNextEntry()) != null) {
                File file = new File(pathfile.getAbsolutePath() + File.separator + zipEntry.getName());
                if (zipEntry.isDirectory()) {
                    file.mkdirs();
                } else {
                    File parentFile = FileHelper.getDirectory(file);
                    if (!parentFile.exists()) {
                        parentFile.mkdirs();
                    }
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    int len = -1;
                    byte[] buf = new byte[1024];
                    while ((len = zis.read(buf)) != -1) {
                        baos.write(buf, 0, len);
                    }
                    baos.close();
                    byte[] fileContent = baos.toByteArray();
                    FileOutputStream fos = new FileOutputStream(file);
                    fos.write(fileContent);
                    fos.close();
                }
            }
            zis.close();
            fis.close();
            return true;
        } catch (Exception e) {
            log.error("解压文件异常", e);
            return false;
        }
    }


    /**
     * 删除目录及目录下文件
     */
    public static boolean deleteDir(File dir) {
        try {
            if (dir.isDirectory()) {
                String[] children = dir.list();
                for (int i = 0; i < children.length; i++) {
                    boolean success = deleteDir(new File(dir, children[i]));
                    if (!success) {
                        return false;
                    }
                }
            }
            return dir.delete();
        } catch (Exception e) {
            log.error("删除目录及目录下文件异常", e);
            return false;
        }
    }

    /**
     * 文件移动
     *
     * @param source 源文件
     * @param dest   目标文件
     */
    public static void copyFileUsingFileStreams(File source, File dest) throws IOException {
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(source).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
        } finally {
            for (FileChannel fileChannel : Arrays.asList(inputChannel, outputChannel)) {
                fileChannel.close();
            }
        }
    }


    public static void main(String[] args) throws IOException {
//        String sFolder = "/Users/wlz/Desktop/home/fota/share/upgrade--package-done-file//20230112/encrypt-4497a58c-9ea0-4648-b65e-a529fce6b3be.zip";
//        File sfile = new File(sFolder);
//        File tfile = new File("/Users/wlz/Desktop/encrypt-4497a58c-9ea0-4648-b65e-a529fce6b3be.zip");
//        if (!tfile.exists()) {
//            tfile.mkdirs();
//        }
//        ZipCompressUtil.copyFileUsingFileStreams(sfile,tfile);


        String tarFileDir = "/Users/wlz/Desktop/test111";
        String subfolder = "";
        File dir = new File(tarFileDir, subfolder);
        if (!dir.exists()) {
            dir.mkdirs();
        }

    }


}
